﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="UseCaseBinding.cs" company="">
//   
// </copyright>
// <summary>
//   The use case binding.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace Libium.Bindings
{
	using Libium.UseCases;
	using Libium.Views;

	/// <summary>
	/// The use case binding.
	/// </summary>
	/// <typeparam name="T1">
	/// </typeparam>
	/// <typeparam name="T2">
	/// </typeparam>
	public abstract class UseCaseBinding<T1, T2> : BindableViewBinding<T1, T2>
		where T1 : IUseCase
		where T2 : IView
	{
		#region Constructors and Destructors

		/// <summary>
		/// Initializes a new instance of the <see cref="UseCaseBinding{T1,T2}"/> class.
		/// </summary>
		/// <param name="service">
		/// The service. 
		/// </param>
		/// <param name="useCase">
		/// The use case. 
		/// </param>
		/// <param name="view">
		/// The view. 
		/// </param>
		protected UseCaseBinding(IBindService service, T1 useCase, T2 view)
			: base(service, useCase, view)
		{
		}

		#endregion

		#region Public Methods and Operators

		/// <summary>
		///   The bind.
		/// </summary>
		public override void Bind()
		{
			base.Bind();
			View.ReadOnly = UseCase.ReadOnly;
			UseCase.ReadonlyChanged += OnElementReadonlyChanged;

			View.CopySource = UseCase;
			View.PasteTarget = UseCase;

			EventsBinding(UseCase, View);
		}

		public static void EventsBinding(IUseCase uc, IView v)
		{
			uc.WarningAdded += (u, w) => { v.AddWarning(w.Text); };
			uc.WarningDeleted += (u, w) => { v.RemoveWarning(); };
			foreach (IWarning w in uc.Warnings)
			{
				v.AddWarning(w.Text);
			}

			uc.ErrorAdded += (u, w) => { v.AddError(w.Text); };
			uc.ErrorDeleted += (u, w) => { v.RemoveError(); };
			foreach (IWarning w in uc.Errors)
			{
				v.AddError(w.Text);
			}

			uc.HintAdded += (u, w) => { v.AddHint(w.Text); };
			uc.HintDeleted += (u, w) => { v.RemoveHint(); };
			foreach (IHint w in uc.Hints)
			{
				v.AddHint(w.Text);
			}

			uc.WaitStarted += (u) => { TmpTest(v, u); };
			uc.WaitEnded += (u) => { v.EndWait(u); };
			UseCase ucImpl = uc as UseCase;
			if (ucImpl != null)
			{
				ucImpl.WaitProgressChanged += (u) => { v.SetWaitProgress(u); };
				v.WaitCancelled += (u) => { ucImpl.CancelWait(); };
			}
		}

		static void TmpTest(IView v, IUseCase u)
		{
			v.StartWait(u);
		}

		/// <summary>
		///   The unbind.
		/// </summary>
		public override void Unbind()
		{
			base.Unbind();
			UseCase.ReadonlyChanged -= OnElementReadonlyChanged;
		}

		#endregion

		#region Methods

		/// <summary>
		/// The on element readonly changed.
		/// </summary>
		/// <param name="useCase">
		/// The use case. 
		/// </param>
		private void OnElementReadonlyChanged(IUseCase useCase)
		{
			View.ReadOnly = UseCase.ReadOnly;
		}

		private void TmpSetHint(string hint)
		{
			//View.AddHint(w.Text);
			View.AddHint(hint);
		}

		#endregion
	}
}